﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Achievement.DataModels;
using Achievement.Common;

namespace Achievement.BLL.Provider
{
    public class FolderProvider
    {
        private static readonly FolderProvider instance = new FolderProvider();
        public static FolderProvider Instance
        {
            get { return instance; }
        }
        private FolderProvider() { }

        public List<Folder> GetFolders(long id)
        {
            using (CGKEntities CGK = new CGKEntities())
            {
                if (id == 0)
                {
                    return CGK.Folder.ToList();
                }
                else if (id > 0)
                {
                    return CGK.Folder.Where(f => f.Parent == id).ToList();
                }
                return null;
            }
        }

        public List<VFolder> GetVFolders()
        {
            using (CGKEntities CGK = new CGKEntities())
            {
                string sql = "select *,(select count(id) from folder where parent=a.id) SunCount from folder a where 1=1";
                var query = CGK.ExecuteStoreQuery<VFolder>(sql).ToList();
                return query;
            }
        }

        public List<VFolder> GetVFoldersById(IEnumerable<long> ids)
        {
            if (ids.Count() > 0)
            {
                using (CGKEntities CGK = new CGKEntities())
                {
                    string sql = "select *,(select count(id) from folder where parent=a.id) SunCount from folder a where 1=1 and id in (" + string.Join(",",ids) + ")";
                    var query = CGK.ExecuteStoreQuery<VFolder>(sql).ToList();
                    return query;
                }
            }
            return null;
        }

        public List<VFolder> GetVFoldersByParent(IEnumerable<long> ids)
        {
            if (ids.Count() > 0)
            {
                using (CGKEntities CGK = new CGKEntities())
                {
                    string sql = "select *,(select count(id) from folder where parent=a.id) SunCount from folder a where 1=1";
                    if (ids.Contains(0))
                    {
                        sql += " and a.Parent is null";
                    }
                    else
                    {
                        sql += " and a.Parent in (" + string.Join(",", ids) + ")";
                    }
                    var query = CGK.ExecuteStoreQuery<VFolder>(sql).ToList();
                    return query;
                }
            }
            return null;
        } 

        public List<VFolderUsers> GetVFolderUsersById(long id)
        {
            using (CGKEntities CGK = new CGKEntities())
            {
                return CGK.VFolderUsers.Where(vfu => vfu.IsActive == true && vfu.uid == id).ToList();
            }
        }

        public List<VFolderUsers> GetVFolderUsers()
        {
            using (CGKEntities CGK = new CGKEntities())
            {
                return CGK.VFolderUsers.Where(vfu => vfu.IsActive == true).ToList();
            }
        }

        public Folder GetFolderById(long id)
        {
            using (CGKEntities CGK = new CGKEntities())
            {
                return CGK.Folder.Where(f=>f.ID == id).FirstOrDefault();
            }
        }

        public void DeleteFolderById(long id)
        {
            using (CGKEntities CGK = new CGKEntities())
            {
                Folder folder = CGK.Folder.Where( f => f.ID == id).FirstOrDefault();
                if(folder != null)
                {
                    CGK.Folder.DeleteObject(folder);
                    CGK.SaveChanges();
                }
            }
        }

        public void SaveFolder(Folder f)
        {
            using (CGKEntities CGK = new CGKEntities())
            {
                if (f.ID > 0)
                {
                    CGK.Folder.Attach(f);
                    CGK.ObjectStateManager.ChangeObjectState(f, System.Data.EntityState.Modified);
                }
                else
                {
                    CGK.Folder.AddObject(f);
                }
                CGK.SaveChanges();
            }
        }

        public List<FolderUsers> GetFolderUsersByFId(long fid)
        {
            using (CGKEntities CGK = new CGKEntities())
            {
                return CGK.FolderUsers.Where(fu=>fu.FID == fid).ToList();
            }
        }

        public List<long> GetFidsByUid(long uid)
        {
            using (CGKEntities CGK = new CGKEntities())
            {
                return CGK.FolderUsers.Where(fu => fu.UID == uid).Select(fu => fu.FID).ToList();
            }
        }

        public List<string> GetAchievementsType()
        {
            using (CGKEntities CGK = new CGKEntities())
            {
                return CGK.Achievements.Select(a=>a.Type).Distinct().ToList();
            }
        }

        public void AddFolderUser(string[] uIds,long fid)
        {
            if (uIds.Length > 0 && uIds[0] != string.Empty)
            {
                using (CGKEntities CGK = new CGKEntities())
                {
                    var fus = CGK.FolderUsers.Where(fu => fu.FID == fid).Select(fu => fu.UID);
                    var uf = from u in uIds where !fus.Contains(long.Parse(u)) select new FolderUsers() { UID = long.Parse(u), FID = fid };
                    foreach (var item in uf)
                    {
                        CGK.FolderUsers.AddObject(item);
                    }
                    CGK.SaveChanges();
                }
            }
        }

        public void DeleteFolderUser(string[] uIds, long fid)
        {
            if (uIds.Length > 0 && uIds[0] != string.Empty)
            {
                List<long> result = new List<string>(uIds).ConvertAll(i => i.SecureToLong());
                using (CGKEntities CGK = new CGKEntities())
                {
                    var fus = CGK.FolderUsers.Where(fu => fu.FID == fid);
                    var uf = (from u in fus where result.Contains(u.UID) select u).ToList();
                    foreach (var item in uf)
                    {
                        CGK.FolderUsers.DeleteObject(item);
                    }
                    CGK.SaveChanges();
                }
            }
        }

        public List<Folder> GetFolderByIds(IEnumerable<long> ids)
        {
            List<Folder> myFolders = new List<Folder>();
            GetFolderTreeByIds(ids, ref myFolders, 0);
            return myFolders;
        }

        public void GetFolderTreeByIds(IEnumerable<long> ids, ref List<Folder> list, int safeLock)
        {
            safeLock++;
            if (safeLock <= 10)
            {
                var mylist = new List<Folder>();
                using (CGKEntities CGK = new CGKEntities())
                {
                    if (ids.Contains(0))
                    {
                        mylist = CGK.Folder.Where(f => f.Parent == null).ToList();
                    }
                    else
                    {
                        List<long?> result = new List<long>(ids).ConvertAll(i => (long?)i);
                        mylist = CGK.Folder.Where(f => result.Contains(f.Parent)).ToList();
                    }
                }
                if (mylist.Count > 0)
                {
                    GetFolderTreeByIds(mylist.Select(l => l.ID), ref list, safeLock);
                }
                list.AddRange(mylist.ToList());
            }
        }

        public List<VFolder> GetVFolderTreeByIds(IEnumerable<long> ids)
        {
            List<VFolder> myFolders = new List<VFolder>();
            if (ids.Contains(0))
            {
                myFolders = GetVFoldersByParent(new long[] { 0 });
            }
            else
            {
                myFolders.AddRange(GetVFoldersById(ids));
            }
            ids = myFolders.Select(f => f.ID);
            GetVFolderTreeByIds(ids, ref myFolders, 0);
            return myFolders;
        }

        public void GetVFolderTreeByIds(IEnumerable<long> ids, ref List<VFolder> list, int safeLock)
        {
            safeLock++;
            if (safeLock <= 10)
            {
                var mylist = new List<VFolder>();
                using (CGKEntities CGK = new CGKEntities())
                {
                    mylist = GetVFoldersByParent(ids);
                }
                if (mylist.Count > 0)
                {
                    GetVFolderTreeByIds(mylist.Select(l => l.ID), ref list, safeLock);
                }
                list.AddRange(mylist.ToList());
            }
        }

        public List<VSumAchievementFolders> SumAchievementByFolders(IEnumerable<Folder> folders)
        {
            List<VSumAchievementFolders> vList = new List<VSumAchievementFolders>();
            using (CGKEntities CGK = new CGKEntities())
            {
                IEnumerable<long?> ids = folders.Select(f=>(long?)f.ID);
                var amt = from a in CGK.Achievements group a by a.Folder into g select new{ Fid = g.Key,Count = g.Count() };
                foreach (var item in folders)
                {
                    var f = amt.Where(a=>a.Fid == item.ID).FirstOrDefault();
                    int count = f == null ? 0 : f.Count;
                    VSumAchievementFolders vsaf = new VSumAchievementFolders() { FID = item.ID, Name = item.Name, Parent = item.Parent, ACount = count };
                    vList.Add(vsaf);
                }
            }
            return vList;
        }

        public List<VSumAchievementFolders> SumAchievementByFolders(IEnumerable<VFolder> folders)
        {
            List<VSumAchievementFolders> vList = new List<VSumAchievementFolders>();
            using (CGKEntities CGK = new CGKEntities())
            {
                IEnumerable<long?> ids = folders.Select(f => (long?)f.ID);
                var amt = from a in CGK.Achievements where a.IsActive group a by a.Folder into g select new { Fid = g.Key, Count = g.Count() };
                foreach (var item in folders)
                {
                    var f = amt.Where(a => a.Fid == item.ID).FirstOrDefault();
                    int count = f == null ? 0 : f.Count;
                    VSumAchievementFolders vsaf = new VSumAchievementFolders() { FID = item.ID, Name = item.Name, Parent = item.Parent, ACount = count };
                    vList.Add(vsaf);
                }
            }
            return vList;
        }

        public List<VSumAchievementFolders> SumAchievementByFolders(IEnumerable<VFolder> folders,bool isAll)
        {
            List<VSumAchievementFolders> vList = new List<VSumAchievementFolders>();
            using (CGKEntities CGK = new CGKEntities())
            {
                IEnumerable<long?> ids = folders.Select(f => (long?)f.ID);
                var amt = from a in CGK.Achievements group a by a.Folder into g select new { Fid = g.Key, Count = g.Count() };
                if (!isAll)
                {
                    amt = from a in CGK.Achievements where a.IsActive group a by a.Folder into g select new { Fid = g.Key, Count = g.Count() };
                }
                foreach (var item in folders)
                {
                    var f = amt.Where(a => a.Fid == item.ID).FirstOrDefault();
                    int count = f == null ? 0 : f.Count;
                    VSumAchievementFolders vsaf = new VSumAchievementFolders() { FID = item.ID, Name = item.Name, Parent = item.Parent, ACount = count };
                    vList.Add(vsaf);
                }
            }
            return vList;
        }
    }
}
